import threading
import socket

import numpy as np
import paddle


class myThread(threading.Thread):
    def __init__(self, client_socket, dic_kw_path, dic_wk_path, modelnet):
        threading.Thread.__init__(self)
        self.client_socket = client_socket
        self.dic_kw = self.Dic_read(dic_kw_path)
        self.dic_wk = self.Dic_read(dic_wk_path)
        self.modelnet = modelnet

    def run(self):
        self.Msg_dispose(self.client_socket)

    def Msg_dispose(self, client_socket):
        # 接收数据
        recevie_data = client_socket.recv(1024).decode('utf-8')
        # 向客户端返回响应数据
        up = str(recevie_data)
        down = self.use(up)
        # print(up,"  ",down)
        client_socket.send(bytes(down, "utf-8"))
        # 关闭客户端连接
        client_socket.close()
        return down

    def use(self, up):
        datastr = up  # input("我说：")
        data, d, db = self.get_tensor(datastr, 100)
        data = paddle.to_tensor(data)
        d = paddle.to_tensor(d)
        db = paddle.to_tensor(db)
        predicts = self.modelnet.infer(data, d, db)
        down = self.get_word(predicts)
        down_str = ""
        for c in down[0]:
            if c == "eos":
                break
            down_str += c
        return down_str

    def Dic_read(self, dic_name):
        dict = np.load(dic_name, allow_pickle='TRUE').item()
        return dict

    def get_tensor(self, word_str, maxlen):
        data_list = []
        mask = []
        # 0: '<PiD>', 1: '<puk>', 2: '<eos>', 3: '<SOS>',
        for char in word_str:
            if len(data_list) == maxlen - 1:
                break
            if char != " ":
                mask.append(1)
                if not char in self.dic_wk.keys():
                    data_list.append(1)
                else:
                    data_list.append(self.dic_wk[char])

        data_list.append(2)
        mask.append(1)
        while len(data_list) < maxlen:
            data_list.append(0)
            mask.append(0)
        seq_len = len(data_list)
        return data_list, [seq_len], mask

    def get_word(self, ts):
        # ts是一个tensor变量，为batch_size,seq_len
        ts = ts.numpy()
        str_batch = []
        for i in range(ts.shape[0]):
            str_list = []
            for j in range(ts.shape[1]):
                str_list.append(self.dic_kw[ts[i][j]])
            str_batch.append(str_list)
        return str_batch


class deploy():
    def __init__(self, modelnet, dic_kw_path, dic_wk_path):
        super(deploy, self).__init__()
        print("开启部署模式")
        hostname = "127.0.0.1"
        port = 8080
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind((hostname, 8080))
        self.server_socket.listen(128)
        self.modelnet = modelnet

        self.dic_kw_path = dic_kw_path
        self.dic_wk_path = dic_wk_path

    def startDeploy(self):
        while True:
            client_socket, client_address = self.server_socket.accept()
            print("[%s, %s]用户连接上了" % client_address)
            thread = myThread(client_socket, self.dic_kw_path, self.dic_wk_path, self.modelnet)
            thread.start()
